#include "Cube.h"
#include "Floor.h"
#include "Light.h"
#include "Camera.h"
#include <iostream>

using namespace Nitro;

int main()
{
    std::ios::sync_with_stdio(false);
    glfwInit();
    Renderer::Init({4, 6, 16});
    auto window = glfwCreateWindow(1440, 960, APP_NAME, 0, 0);
    glfwMakeContextCurrent(window);
    gladLoadGLLoader(GLADloadproc(glfwGetProcAddress));
    glfwSetWindowSizeCallback(
        window, [](GLFWwindow*, int w, int h) { glViewport(0, 0, w, h); });

    Cube cube1(2.f), cube2(5.f);
    Floor floor(400.0f);
    Light light;
    FpsCamera camera;
    light.position = {0.f, 10.f, 0.f};
    cube1.position = {0.f, 2.f, 0.f};
    camera.position = glm::vec3(0.0f, 1.0f, -10.0f);
    cube1.rotate(1.f, 0.f, 1.f);
    cube2.position = {10.f, 10.f, 10.f};

    double currentTime, prevTime = glfwGetTime();
    float dx, dy, delta;

    glEnable(GL_DEPTH_TEST);
    while (!glfwWindowShouldClose(window))
    {
        currentTime = glfwGetTime();
        delta = (currentTime - prevTime) * 1.5f;

        if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
        {
            dy += delta;
        }
        if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
        {
            dy -= delta;
        }
        if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
        {
            dx -= delta;
        }
        if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
        {
            dx += delta;
        }
        camera.processInput(dx, dy);
        dx = dy = 0.0;

        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        {
            camera.position += delta * 10.0f * camera.direction;
        }
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        {
            camera.position -= delta * 10.0f * camera.direction;
        }

        Renderer::Clear();
        Renderer::ClearColor();
        camera.render();
        light.render();
        cube1.pipeline.setUniform("light.position", light.position);
        cube1.pipeline.setUniform("light.color", light.color);
        cube1.pipeline.setUniform("light.ambient", light.ambient);
        cube1.pipeline.setUniform("light.diffuse", light.diffuse);
        cube1.pipeline.setUniform("light.specular", light.specular);
        cube1.pipeline.setUniform("viewPos", camera.position);
        cube2.pipeline.setUniform("light.position", light.position);
        cube2.pipeline.setUniform("light.color", light.color);
        cube2.pipeline.setUniform("light.ambient", light.ambient);
        cube2.pipeline.setUniform("light.diffuse", light.diffuse);
        cube2.pipeline.setUniform("light.specular", light.specular);
        cube2.pipeline.setUniform("viewPos", camera.position);
        cube1.render();
        cube2.render();
        floor.render();

        prevTime = currentTime;
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}